﻿using System;
using System.Diagnostics.Contracts;

namespace Cloak.Mvvm.Bindings
{
	/// <summary>
	/// Describes a reference to an object's property which may change over time
	/// </summary>
	[ContractClass(typeof(IPropertyReferenceContract))]
	public interface IPropertyReference
	{
		/// <summary>
		/// Occurs when the value of the <see cref="Value"/> changes
		/// </summary>
		event EventHandler Changed;

		/// <summary>
		/// Gets or sets the value of the object's property
		/// </summary>
		object Value { get; set; }

		/// <summary>
		/// Determines whether the value of the specified property is not equal to the value of this property
		/// </summary>
		/// <param name="otherProperty">The property whose value will be compared to the value of this property</param>
		/// <returns>Whether the value of the specified property does not equal the value of this property</returns>
		bool ValueDiffersFrom(IPropertyReference otherProperty);
	}

	[ContractClassFor(typeof(IPropertyReference))]
	internal abstract class IPropertyReferenceContract : IPropertyReference
	{
		event EventHandler IPropertyReference.Changed
		{
			add {}
			remove {}
		}

		object IPropertyReference.Value
		{
			get { return null; }
			set {}
		}

		bool IPropertyReference.ValueDiffersFrom(IPropertyReference otherProperty)
		{
			Contract.Requires(otherProperty != null);

			return false;
		}
	}
}